﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using ScrumFactory.Composition.ViewModel;
using ScrumFactory.Composition;
using ScrumFactory.Services;
using System.Collections.ObjectModel;
using ScrumFactory.Windows.Helpers;

namespace ScrumFactory.ProjectTeam.ViewModel {

    

    public class MemberLookupViewModel : BasePanelViewModel, IMemberLookupViewModel, IWindowViewModel, INotifyPropertyChanged {
               
        private string searchFilterText;

        private IMemberLookupView view;
        
        private Role roleToAdd;
        private Action<IMemberViewModel> onSelectMemberAction;

        private DelayAction delayFilter;

        private ICollection<IMemberViewModel> members;

        private Occupations occupationFilter;

        private System.Windows.Data.CollectionViewSource membersViewSource;

        private IEventAggregator aggregator;
        private ITeamService teamServices;        
        private IBackgroundExecutor executor;

        public IMemberLookupView View {
            get {
                return view;
            }
            set {
                view = value;
                view.Model = this;
            }
        }

        public MemberLookupViewModel(IEventAggregator eventAggregator, ITeamService teamServices, IBackgroundExecutor backgroundExecutor, Role roleToAdd, Action<IMemberViewModel> onSelectMemberAction) {            
            this.roleToAdd = roleToAdd;
            this.onSelectMemberAction = onSelectMemberAction;

            InitViewModel(eventAggregator, teamServices, backgroundExecutor);
        }

        public MemberLookupViewModel(IEventAggregator eventAggregator, ITeamService teamServices, IBackgroundExecutor backgroundExecutor) {
            InitViewModel(eventAggregator, teamServices, backgroundExecutor);
        }

        private void InitViewModel(IEventAggregator eventAggregator, ITeamService teamServices, IBackgroundExecutor backgroundExecutor) {
            this.aggregator = eventAggregator;
            this.teamServices = teamServices;
            this.executor = backgroundExecutor;

            View = new MemberLookup();

            MoveWindowCommand = new DelegateCommand(() => { ((System.Windows.Window)View).DragMove(); });
            CloseWindowCommand = new DelegateCommand(() => { ((System.Windows.Window)View).Close(); });

            MaximizeWindowCommand = new DelegateCommand(() => {
                if (View.WindowState == System.Windows.WindowState.Maximized)
                    View.WindowState = System.Windows.WindowState.Normal;
                else
                    View.WindowState = System.Windows.WindowState.Maximized;
            });

            SelectMemberCommand = new DelegateCommand<IMemberViewModel>(SelectMember);

            executor.StartBackgroundTask<ICollection<MemberProfile>>(LoadMembers, OnMembersLoaded);
                

            membersViewSource = new System.Windows.Data.CollectionViewSource();
            membersViewSource.Filter += new System.Windows.Data.FilterEventHandler(membersViewSource_Filter);
            delayFilter = new DelayAction(1000, new DelayAction.ActionDelegate(() => { if(FilteredMembers!=null) FilteredMembers.Refresh(); }));

            OccupationFilter = Occupations.A_3QUARTER_BUSY;
        }

        private void SelectMember(IMemberViewModel memberVM) {

            memberVM.IsMemberSelected = true;

            if (onSelectMemberAction != null)
                onSelectMemberAction.Invoke(memberVM);
        }

        private void membersViewSource_Filter(object sender, System.Windows.Data.FilterEventArgs e) {

            IMemberViewModel vm = e.Item as IMemberViewModel;
            if (vm == null)
                return;

            bool searchAccepted = false;
            bool occupationAccepted = false;

            if (String.IsNullOrWhiteSpace(SearchFilterText))
                searchAccepted = true;
            else {
                string search = SearchFilterText.ToUpper();
                searchAccepted = vm.MemberProfile.FullName.ToUpper().Contains(search) || vm.MemberProfile.Skills.ToUpper().Contains(search);
            }

            occupationAccepted = vm.MemberProfile.DayOccupation <= (int)OccupationFilter;

            e.Accepted = searchAccepted && occupationAccepted;

        }

        private ICollection<MemberProfile> LoadMembers() {            
            IsLoadingData = true;
            return teamServices.GetAllMembers();                
        }

        private void OnMembersLoaded(ICollection<MemberProfile> members) {
            ObservableCollection<IMemberViewModel> membersVM = new ObservableCollection<IMemberViewModel>();
            if (members != null)
                foreach (MemberProfile m in members)
                    membersVM.Add(new ViewModel.MemberViewModel(m));
            Members = membersVM;

            membersViewSource.Source = Members;

            IsLoadingData = false;

            OnPropertyChanged("FilteredMembers");

        }


        public ICollectionView FilteredMembers {
            get {
                return membersViewSource.View;
            }            
        }

        public ICollection<IMemberViewModel> Members {
            get {
                return members;
            }
            set {
                members = value;
                OnPropertyChanged("Members");
            }
        }

        public string Title {
            get {
                if (roleToAdd == null)
                    return Properties.Resources.Team;

                return String.Format(Properties.Resources.Adding_new_ROLE, roleToAdd.RoleName);
            }
        }

        public ICommand SelectMemberCommand { get; private set; }

        /// <summary>
        /// Gets or sets the search filter text.
        /// </summary>
        /// <value>The search filter text.</value>
        public string SearchFilterText {
            get {
                return this.searchFilterText;
            }
            set {
                this.searchFilterText = value;
                OnPropertyChanged("SearchFilterText");
                delayFilter.StartAction();
            }
        }

        public Occupations OccupationFilter {
            get {
                return occupationFilter;
            }
            set {
                occupationFilter = value;
                OnPropertyChanged("OccupationFilter");
                if (FilteredMembers != null) FilteredMembers.Refresh();
                
            }
        }

       

        #region IWindowViewModel Members

        object IWindowViewModel.View {
            get {
                return this.View;
            }
            set {
                this.View = (IMemberLookupView)view;
            }
        }

        public void Show() {
            ((System.Windows.Window)View).Owner = System.Windows.Application.Current.MainWindow;
            ((System.Windows.Window)View).ShowDialog();
        }

        /// <summary>
        /// Gets the move window command.
        /// </summary>
        /// <value>The move window command.</value>
        public ICommand MoveWindowCommand { get; private set; }

        /// <summary>
        /// Gets the close window command.        
        /// </summary>        
        /// <value>The close window command.</value>
        public ICommand CloseWindowCommand { get; private set; }
         

        /// <summary>
        /// Gets the minimize window command.
        /// </summary>        
        /// <value>The minimize window command.</value>
        public ICommand MinimizeWindowCommand {
            get { return null; }
        }

        /// <summary>
        /// Gets the maximize window command.
        /// </summary>        
        /// <value>The maximize window command.</value>
        public ICommand MaximizeWindowCommand {
            get;
            private set;
        }
        

        #endregion

       
    }
}
